<template>
  <div class="upload-panel">
    <!-- 操作按钮区域 -->
    <div class="toolbar">
      <!-- 整合ImageUploader功能 -->
      <div>
        <el-button class="tool-btn" @click="triggerFileInput">
          <el-icon>
            <Upload />
          </el-icon>
          <span>题目批量上传</span>
        </el-button>
        <!-- 
          -段代码是一个隐藏的文件上传输入框(input)，它的主要功能和作用如下：
          1. 基本功能：
             - `type="file"`：声明这是一个文件选择输入框
             - `accept="image/*"`：限制只能选择图片文件（所有图片格式）
             - `multiple`：允许选择多个文件
           2. 交互设计：
              - `hidden`：隐藏原生文件选择控件，通过自定义按钮触发
              - `ref="fileInput"`：在Vue中引用这个DOM元素，这是vue特有的”用于注册模板引用“
              - `@change="handleFileUpload"`：当用户选择文件后触发handleFileUpload方法
            3. 使用场景：
              - 通常配合一个自定义的"上传"按钮使用
              - 点击自定义按钮时通过JavaScript触发这个隐藏input的click事件
              - 用户实际选择文件的操作是通过这个隐藏input完成
            4. 为什么这样设计：
              - 原生文件输入框样式难以自定义
              - 隐藏后可以通过更美观的自定义按钮触发文件选择
              - 保持功能完整性的同时提升UI体验
            5. 相关方法：
              - 在组件中会有triggerFileInput方法（在上面）来触发这个input的点击：

             ```js
               const triggerFileInput = () => {
                    fileInput.value.click()
               } 
             ```
         -->
        <input type="file" accept="image/*" @change="handleFileUpload" ref="fileInput" multiple hidden>
      </div>

      <el-button class="tool-btn" @click="openBatchSourceDialog">
        <el-icon>
          <More />
        </el-icon>
        <span>来源批量设置</span>
      </el-button>
    </div>

    <!-- 图片展示区域 -->
    <div class="image-container" ref="containerEl">
      <div v-for="(img, index) in images" :key="img.key" class="image-item">
        <!-- 整合ImagePreview功能 -->
        <div class="preview-container">
          <img :src="img.url" :alt="'图片' + index" class="preview-image" :style="{
            width: `${img.width > containerWidth ? containerWidth : img.width}px`,
            height: 'auto'
          }" />
          <el-button 
            class="delete-btn"
            @click="removeImage(img)"
            :icon="Delete"
            circle
          ></el-button>
        </div>

        <!-- 整合QuestionForm功能 -->
        <div class="metadata-form">
          <div class="form-row">
            <div class="form-item">
              <label>题目类型：</label>
              <el-select v-model="img.metadata.questionType" @change="handleQuestionTypeChange(img, $event)" class="form-select">
                <el-option v-for="type in questionTypes" :key="type.value" :label="type.name" :value="type.value" />
              </el-select>
            </div>
            <div class="form-item" style="flex: 0 0 50px;">
              <label>分值：</label>
              <el-input v-model.number="img.metadata.score" @input="(val) => validateNumber(val, img.metadata, 'score', 2)"
                class="form-input" placeholder="分值" />
            </div>
            <div class="form-item" style="flex: 0 0 50px;">
              <label>难度：</label>
              <el-input v-model.number="img.metadata.difficulty"
                @input="(val) => validateNumber(val, img.metadata, 'difficulty', 2)" class="form-input" placeholder="难度" />
            </div>
            <div class="form-item" style="flex: 1;">
              <label>答案：</label>
              <div class="answer-input-container">
                <!-- 左侧1/4：文本答案输入框 -->
                <div class="answer-section text-answer">
                  <el-input 
                    v-model="img.metadata.answer" 
                    @change="updateImageMetadata(img)" 
                    class="anser-text"
                    placeholder="请输入文本答案" 
                  />
                </div>
                
                <!-- 中间1/4：上传图片答案按钮 -->
                <div class="answer-section image-answer">
                  <el-button 
                    class="answer-btn" 
                    @click="openImageAnswerDialog(img)"
                  >
                    <el-icon><Upload /></el-icon>
                    <span style="display:none;">图片</span>
                  </el-button>
                </div>
                
                <!-- 右侧1/4：富文本答案按钮 -->
                <div class="answer-section rich-text-answer">
                  <el-button 
                    class="answer-btn" 
                    @click="openRichTextAnswerDialog(img)"
                  >
                    <el-icon><Edit /></el-icon>
                    <span style="display:none;">富文本</span>
                  </el-button>
                </div>
              </div>
            </div>
            <div class="form-item">
              <label style="visibility: hidden;">占位</label>
              <el-button type="default" @click="submitImage(img)" style="margin-top: 5px;width: 100%; height: 32px;">
                本题提交
              </el-button>
            </div>
          </div>

          <div class="form-row">
            <!-- 来源选择器 -->
            <el-cascader v-model="img.metadata.cascaderValue" :options="cascaderOptions" :props="cascaderProps"
              @change="handleCascaderChange(img, $event)" placeholder="请选择题目来源" style="width: 100%;" />
          </div>

          <div class="form-item full-width">
            <label>知识点标签：</label>
            <!-- 知识点标签区域（支持拖拽添加） -->
            <div class="tags-drop-container" @drop="handleTagDrop(img, $event)" @dragover.prevent>
              <el-tag v-for="tag in img.metadata.knowledgeTags" :key="tag.id" closable @close="removeTag(img, tag)"
                class="tag-item">
                {{ tag.title }}
              </el-tag>
              <div v-if="!img.metadata.knowledgeTags || img.metadata.knowledgeTags.length === 0" class="drop-hint">
                拖拽知识节点到此处添加标签
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 批量设置来源对话框 -->
  <el-dialog 
    v-model="showBatchSourceDialog"
    title="批量设置题目来源"
    width="30%"
  >
    <el-cascader 
      v-model="batchCascaderValue"
      :options="cascaderOptions"
      :props="cascaderProps"
      placeholder="请选择题目来源"
      style="width: 100%;"
    />
    <template #footer>
      <el-button @click="showBatchSourceDialog = false">取消</el-button>
      <el-button type="primary" @click="applyBatchSource">确定</el-button>
    </template>
  </el-dialog>

  <!-- 图片答案上传对话框 -->
  <el-dialog
    v-model="showImageAnswerDialog"
    title="上传图片答案"
    width="50%"
  >
    <el-upload
      class="image-answer-uploader"
      drag
      action="#"
      :auto-upload="false"
      :on-change="handleImageAnswerUpload"
      :show-file-list="true"
      accept="image/*"
    >
      <el-icon class="el-icon--upload">
        <Upload />
      </el-icon>
      <div class="el-upload__text">
        将文件拖到此处，或<em>点击上传</em>
      </div>
    </el-upload>
    <template #footer>
      <el-button @click="showImageAnswerDialog = false">取消</el-button>
      <el-button type="primary" @click="confirmImageAnswer">确定</el-button>
    </template>
  </el-dialog>

  <!-- 富文本编辑器对话框 -->
  <el-dialog
    v-model="showRichTextDialog"
    title="富文本答案编辑"
    width="80%"
    top="5vh"
  >
    <QuillEditor 
      ref="quillEditorRef"
      v-model:content="richTextContent" 
      contentType="html"
      theme="snow"
      style="min-height: 400px;"
    />
    <template #footer>
      <el-button @click="showRichTextDialog = false">取消</el-button>
      <el-button type="primary" @click="confirmRichText">确定</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed, useTemplateRef } from 'vue'
import { ElButton, ElSelect, ElOption, ElInput, ElCascader, ElTag, ElMessage, ElDialog, ElUpload } from 'element-plus'
import { Eleme, More, Upload, Delete, Edit } from '@element-plus/icons-vue'
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import questionService from '../../services/questions'
import questionTypeService from '../../services/questionTypes'
import questionSource from '@/services/questionSource'
import localforage from 'localforage' // 引入localforage操作IndexedDB
ElMessage
// ==================== 状态管理 ====================
/**
 * 存储所有已上传图片的响应式数组
 * @type {import('vue').Ref<Array>}
 */
const images = ref([]) // 图片列表

/**
 * IndexedDB存储实例，用于持久化存储图片数据
 * @type {LocalForage}
 */
const imageStore = localforage.createInstance({ // 创建IndexedDB存储实例
  name: 'image-upload-store',
  driver: localforage.INDEXEDDB
})

// 统一元数据更新函数
const updateImageMetadata = async (img) => {
  try {
    const existing = await imageStore.getItem(img.key)
    if (existing) {
      // 创建metadata的深拷贝，移除响应式特性
      const plainMetadata = JSON.parse(JSON.stringify(img.metadata))
      
      await imageStore.setItem(img.key, {
        ...existing,
        metadata: plainMetadata
      })
    }
  } catch (error) {
    console.error('元数据更新失败:', error)
  }
}

/**
 * 图片容器DOM元素的引用
 * @type {import('vue').Ref<HTMLElement|null>}
 */
const containerEl = ref(null) // 图片容器引用

/**
 * 存储题目类型的响应式数组，用于题目类型下拉选择
 * @type {import('vue').Ref<Array>}
 */
const questionTypes = ref([]) // 题目类型

/**
 * 存储级联选择器选项的响应式数组，用于题目来源选择
 * @type {import('vue').Ref<Array>}
 */
const cascaderOptions = ref([]) // 级联选择器选项

/**
 * 文件输入DOM元素的引用
 * @type {import('vue').Ref<HTMLInputElement|null>}
 */
const fileInput = useTemplateRef('fileInput') // 文件输入引用

/**
 * 级联选择器属性配置
 * @type {Object}
 * 原来的value是获取对应的value也就是文字内容的，
 * 但是现在是获取对应id的，满足数据库存储要求
 */
const cascaderProps = {
  value: 'id',
  expandTrigger: 'hover'
}

// 批量设置来源相关状态
const showBatchSourceDialog = ref(false)
const batchCascaderValue = ref([])

// 答案相关状态
const showImageAnswerDialog = ref(false)
/**
 * 控制富文本编辑器对话框显示状态的响应式变量
 * 当值为 true 时显示富文本编辑器对话框，false 时隐藏
 * @type {import('vue').Ref<boolean>}
 */
const showRichTextDialog = ref(false)
/**
 * 存储当前正在编辑富文本答案的图片对象引用
 * 用于在富文本编辑器中识别是哪张图片正在被编辑
 * @type {import('vue').Ref<Object|null>}
 */
const currentImageForImageAnswer = ref(null)
/**
 * 存储当前正在编辑富文本答案的图片对象引用
 * 用于在确认保存时知道应该更新哪张图片的元数据
 * @type {import('vue').Ref<Object|null>}
 */
const currentImageForRichText = ref(null)
/**
 * 存储图片答案对话框中选择的图片文件
 * 用于在确认时获取用户选择的图片文件
 * @type {import('vue').Ref<Object|null>}
 */
const dialogImageFile = ref(null)
/**
 * 存储富文本编辑器中的内容
 * 用于在富文本编辑器组件和当前图片之间传递富文本内容
 * @type {import('vue').Ref<string>}
 */
const richTextContent = ref('')

/**
 * 计算属性，根据容器元素的宽度动态计算图片容器宽度
 * @returns {number} 容器宽度（像素）
 */
const containerWidth = computed(() => {
  return containerEl.value?.offsetWidth || 800
})

// ==================== 图片上传处理 ====================
/**
 * 触发文件选择对话框
 */
const triggerFileInput = () => {
  fileInput.value?.click()
}

/**
 * 处理文件上传事件
 * @param {Event} e - 文件上传事件对象
 */
const handleFileUpload = async (e) => {
  /**
   * 从事件对象中获取的文件列表，已过滤出图片文件
   * @type {File[]}
   */
  const files = Array.from(e.target.files).filter(file => file.type.startsWith('image/'))
  if (files.length === 0) {
    ElMessage.warning('请选择图片文件')
    return
  }

  try {
    // 加载所有图片并获取尺寸信息
    const loadedImages = await Promise.all(files.map(file => 
      new Promise((resolve) => {
        const blobUrl = URL.createObjectURL(file)
        const img = new Image()
        
        img.onload = function() {
          resolve({
            file,
            blobUrl,
            width: img.width,
            height: img.height
          })
        }
        
        img.onerror = (error) => {
          console.error('图片加载失败:', error)
          URL.revokeObjectURL(blobUrl)
          resolve(null)
        }
        
        img.src = blobUrl
      })
    ))

    // 过滤掉加载失败的图片
    const validImages = loadedImages.filter(img => img !== null)
    const newImages = []

    // 检查重复并创建图片数据
    for (const {file, blobUrl, width, height} of validImages) {
      const isDuplicate = [
        ...images.value,
        ...newImages
      ].some(img => 
        img.file.name === file.name && 
        img.file.size === file.size
      )

      if (isDuplicate) {
        ElMessage.warning(`图片 ${file.name} 已在处理中`)
        URL.revokeObjectURL(blobUrl)
        continue
      }

      const storageKey = `img_${Date.now()}_${Math.random().toString(36).slice(2)}`
      const imageData = {
        url: blobUrl,
        key: storageKey,
        file: file,
        metadata: {
          questionType: '',
          score: 2,
          difficulty: 2,
          answer: '',
        //  imageAnswer: null, // 图片答案
          htmlAnswer: '', // 富文本答案
          knowledgeTags: [],
          cascaderValue: [],
          sourceType: '',
          sourceContent: ''
        },
        width: width,
        height: height
      }

      // 存储到IndexedDB
      await imageStore.setItem(storageKey, {
        file: file,
        metadata: imageData.metadata,
        width: width,
        height: height
      })
      
      newImages.push(imageData)
    }

    // 批量更新图片列表
    if (newImages.length > 0) {
      images.value = [...images.value, ...newImages]
      ElMessage.success(`刚刚加载了${newImages.length}张图片`)
    }
  } catch (error) {
    console.error('图片处理失败:', error)
    ElMessage.error('图片处理失败')
  } finally {
    // 重置文件选择框
    e.target.value = ''
  }
}

// ==================== 答案管理 ====================
/**
 * 打开图片答案上传对话框
 * @param {Object} img - 图片对象
 */
const openImageAnswerDialog = (img) => {
  currentImageForImageAnswer.value = img
  showImageAnswerDialog.value = true
}

/**
 * 打开富文本答案编辑对话框
 * @param {Object} img - 图片对象
 */
const openRichTextAnswerDialog = (img) => {
  currentImageForRichText.value = img
  /**
   * 所以整个流程是：
   * 
   * 用户点击富文本按钮 -> 加载已有内容到编辑器
   * 用户在编辑器中编辑 -> 内容实时同步到 richTextContent
   * 用户点击确定 -> 将 richTextContent 保存到图片元数据中，并清空 richTextContent 为下次使用做准备
   * 这样设计的好处是：
   * 
   * 每次打开编辑器时都能加载之前保存的内容
   * richTextContent 作为一个临时变量，在每次使用后清空，避免数据混淆
   * 通过 currentImageForRichText 来跟踪当前正在编辑的是哪张图片
   */
  richTextContent.value = img.metadata.htmlAnswer || ''
  showRichTextDialog.value = true
}

/**
 * 处理图片答案上传
 * @param {Object} file - 上传的文件对象
 */
const handleImageAnswerUpload = (file) => {
  dialogImageFile.value = file
  return false // 阻止自动上传
}

/**
 * 确认图片答案上传
 */
const confirmImageAnswer = async () => {
  if (!dialogImageFile.value || !currentImageForImageAnswer.value) {
    ElMessage.warning('请选择图片文件')
    return
  }

  try {
    const file = dialogImageFile.value.raw
    const imageUrl = URL.createObjectURL(file)
    
    // 将图片答案URL保存到图片元数据中
    currentImageForImageAnswer.value.metadata.imageAnswer = {
      url: imageUrl,
      fileName: file.name,
      fileSize: file.size
    }
    
    // 更新持久化存储
    await updateImageMetadata(currentImageForImageAnswer.value)
    
    showImageAnswerDialog.value = false
    dialogImageFile.value = null
    currentImageForImageAnswer.value = null
    ElMessage.success('图片答案暂存成功')
  } catch (error) {
    console.error('图片答案上传失败:', error)
    ElMessage.error('图片答案上传失败')
  }
}

/**
 * 确认富文本答案保存
 */
const confirmRichText = async () => {
  if (!currentImageForRichText.value) {
    ElMessage.error('未找到对应的图片对象')
    return
  }

  try {
    // 将富文本答案保存到图片元数据中（靠currentImageForRichText 去对应的图片对象）
    currentImageForRichText.value.metadata.htmlAnswer = richTextContent.value
    
    // 更新持久化存储
    await updateImageMetadata(currentImageForRichText.value)
    
    showRichTextDialog.value = false
    currentImageForRichText.value = null
    richTextContent.value = ''
    ElMessage.success('编辑已暂存，未提交之前不要关闭页面否则丢失') //其实不会丢失，一i那位存到indexed中了
  } catch (error) {
    console.error('富文本答案保存失败:', error)
    ElMessage.error('富文本答案保存失败')
  }
}

// ==================== 元数据管理 ====================
/**
 * 处理题目类型变更 用于触发及时对indexed的数据更新
 * @param {String} selectedValue - 选中的题目类型
 */
const handleQuestionTypeChange = (img, selectedValue) => {
  img.metadata.questionType = selectedValue
  updateImageMetadata(img)
}

/**
 * 处理级联选择器变更 用于触发及时对indexed的数据更新
 * @param {Object} img - 图片对象
 * @param {Array} value - 级联选择值
 */
const handleCascaderChange = (img, value) => {
  img.metadata.cascaderValue = value
  updateImageMetadata(img)
}

// 打开批量设置对话框
const openBatchSourceDialog = () => {
  showBatchSourceDialog.value = true
}

// 应用批量设置
const applyBatchSource = () => {
  images.value.forEach(img => {
    img.metadata.cascaderValue = [...batchCascaderValue.value]
    updateImageMetadata(img)
  })
  showBatchSourceDialog.value = false
}

/**
 * 移除标签
 * @param {Object} img - 图片对象
 * @param {String} tag - 被移除的标签
 */
const removeTag = (img, tag) => {
  // 根据标签ID查找索引
  /**
   * 被移除标签在数组中的索引
   * @type {number}
   */
  const index = img.metadata.knowledgeTags.findIndex(t => t.id === tag.id)
  if (index !== -1) {
    img.metadata.knowledgeTags.splice(index, 1)
    updateImageMetadata(img)
  }
}

/**
 * 处理标签拖拽添加
 * @param {Object} img - 图片对象
 * @param {DragEvent} e - 拖拽事件
 */
const handleTagDrop = (img, e) => {
  e.preventDefault()
  try {
    /**
     * 从拖拽事件中解析的数据
     * @type {Object}
     */
    const nodeData = JSON.parse(e.dataTransfer.getData('application/json'))
    // console.log(nodeData.id)
    if (nodeData && nodeData.id) {
      /**
       * 检查标签是否已存在的布尔值
       * @type {boolean}
       */
      // 检查是否已存在相同ID的标签
      const exists = img.metadata.knowledgeTags.some(tag => tag.id === nodeData.id)
      if (!exists) {
        img.metadata.knowledgeTags = [
          ...img.metadata.knowledgeTags,
          { id: nodeData.id, title: nodeData.title }
        ]
        updateImageMetadata(img)
      }
    }
  } catch (error) {
    console.error('解析拖拽数据失败:', error)
  }
}

/**
 * 验证数字输入
 * @param {String|Number} rawValue - 原始输入值
 * @param {Object} target - 目标对象
 * @param {String} field - 字段名
 * @param {Number} defaultValue - 默认值
 */
const validateNumber = (rawValue, target, field, defaultValue) => {
  if (rawValue === '') {
    target[field] = defaultValue;
  } else {
    const numValue = Number(rawValue);
    if (isNaN(numValue)) {
      target[field] = defaultValue;
    } else if (field == 'difficulty' && numValue > 5) {
      ElMessage.error('数值不能超过5');
      target[field] = 5;
    } else {
      target[field] = numValue;
    }
  }
  
  // 更新元数据
  const img = images.value.find(img => img.metadata === target);
  if (img) updateImageMetadata(img);
}

// ==================== 数据初始化 ====================
/**
 * 初始化题目类型
 */
async function initQuestionTypes() {
  try {
    /**
     * 从服务端获取的题目类型数据
     * @type {Array}
     */
    const types = await questionTypeService.fetchQuestionTypes()
    questionTypes.value = types.data.map(item => ({
      value: item.id, // 存储类型ID而非值
      name: item.name
    }))
  } catch (error) {
    console.error('获取题目类型失败:', error)
  }
}
/**
 * 初始化来源选项
 * 语法: async function initSourceOptions()
 * 作用: 获取题目来源数据并构建级联选择器选项
 */
async function initSourceOptions() {
  try {
    /**
     * 从服务端获取的级联选择器数据
     * @type {Array}
     */
    const cascaderdata = await questionSource.getCascaderOptions()
    cascaderOptions.value = cascaderdata.data
  } catch (error) {
    console.error('获取题目来源分类失败:', error)
  }
}

/**
 * 从IndexedDB加载图片
 */
async function initImagesFromIndexedDB() {
  /**
   * 从IndexedDB中加载的已存储图片数组
   * @type {Array}
   */
  const storedImages = []
  try {
    await imageStore.iterate((value, key) => {
      if (key.startsWith('img_')) {
        // 重新生成Blob URL
        /**
         * 从存储的文件重新生成的Blob URL
         * @type {string}
         */
        const blobUrl = URL.createObjectURL(value.file)
        storedImages.push({
          url: blobUrl,
          key: key,
          file: value.file,
          metadata: value.metadata,
          width: value.width,
          height: value.height
        })
      }
    })
    images.value = storedImages
  } catch (error) {
    console.error('从IndexedDB加载图片失败:', error)
  }
}

// ==================== 数据提交 ====================
/**
 * 删除图片
 * @param {Object} img - 要删除的图片对象
 */
const removeImage = async (img) => {
  try {
    // 1. 从IndexedDB删除
    await imageStore.removeItem(img.key);
    
    // 2. 从图片数组移除
    images.value = images.value.filter(item => item.key !== img.key);
    
    // 3. 释放Blob URL
    URL.revokeObjectURL(img.url);
    
    // 4. 释放图片答案的Blob URL（如果存在）
    if (img.metadata.imageAnswer && img.metadata.imageAnswer.url) {
      URL.revokeObjectURL(img.metadata.imageAnswer.url);
    }
    
    ElMessage.success('图片已删除');
  } catch (error) {
    console.error('删除失败:', error);
    ElMessage.error('删除失败: ' + error.message);
  }
}

/**
 * 提交图片
 * @param {Object} imageData - 图片数据
 */
const submitImage = async (imageData) => {
  try {
  
    const formData = new FormData()

    // 添加元数据字段 - 使用后端模型字段名
    formData.append('type', imageData.metadata.questionType)
    formData.append('points', imageData.metadata.score)  // 后端模型字段名是 points
    formData.append('difficulty', imageData.metadata.difficulty)
    formData.append('answer', imageData.metadata.answer)
    
    // 添加富文本答案（如果存在）
    if (imageData.metadata.htmlAnswer) {
      console.log("我是富文本")
      formData.append('htmlAnswer', imageData.metadata.htmlAnswer)
    }
    
    // 添加题目图片 - 使用后端模型字段名
    if (imageData.file) {
      formData.append('image', imageData.file)  // 后端模型字段名是 image
    }
    
    // 添加图片答案（如果存在）
    if (imageData.metadata.imageAnswer && imageData.metadata.imageAnswer.file) {
      formData.append('imageAnswer', imageData.metadata.imageAnswer.file)
    }

     // 修改tags字段，只发送id数组给后端
    const tagIds = imageData.metadata.knowledgeTags.map(tag => tag.id);
    tagIds.forEach(id => {
      formData.append('tags', id); // 注意字段名保持一致
    });
    
    imageData.metadata.cascaderValue.forEach(id => {
      formData.append('source', id); // 注意字段名保持一致
    });
    
    const response = await questionService.createQuestion(formData)

    // 检查响应格式是否包含success字段
    if (response && response.success) {
      console.log('题目创建成功:', response.data)
      ElMessage.success('题目创建成功')
      
      // 清理资源
      URL.revokeObjectURL(imageData.url)
      if (imageData.metadata.imageAnswer && imageData.metadata.imageAnswer.url) {
        URL.revokeObjectURL(imageData.metadata.imageAnswer.url);
      }
      await imageStore.removeItem(imageData.key)
      images.value = images.value.filter(img => img.key !== imageData.key)
    }
  } catch (error) {
    console.error('提交失败:', error)
    //alert('提交失败: ' + error.message)
    ElMessage.error(error.message)
  } finally {
    // 重置文件选择框状态
    fileInput.value.value = ''
  }
}

// ==================== 生命周期管理 ====================

onMounted(async () => {
  await Promise.all([
    initQuestionTypes(),
    initSourceOptions()
  ])
  await initImagesFromIndexedDB() // 从IndexedDB加载图片
})

onUnmounted(() => {
  // 清理所有Blob URL
  images.value.forEach(img => {
    URL.revokeObjectURL(img.url)
    if (img.metadata.imageAnswer && img.metadata.imageAnswer.url) {
      URL.revokeObjectURL(img.metadata.imageAnswer.url);
    }
  })

  // 清理IndexedDB存储（可选，根据需求决定是否保留数据）
  // imageStore.clear()
})
</script>
<style scoped>
/* 整个上传面板的容器样式 */
.upload-panel {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 0px;
}

/* 工具栏样式 */
.toolbar {
  display: flex;
  gap: 10px;
  padding: 12px;
  border-bottom: 1px solid #e4e7ed;
  background: #f5f7fa;
  border-radius: 6px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

/* 工具栏按钮基础样式 */
.tool-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: #ffffff;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s ease;
  font-weight: 500;
  color: #606266;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  font-size: 0.9rem;
}

/* 按钮悬停状态 */
.tool-btn:hover {
  background: #409eff;
  color: white;
  border-color: #409eff;
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(64, 158, 255, 0.2);
}

/* 按钮激活状态 */
.tool-btn:active {
  transform: translateY(0);
  box-shadow: 0 1px 3px rgba(64, 158, 255, 0.2);
}

/* 图片容器样式 */
.image-container {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 15px;
  padding: 12px;
  background: #f5f7fa;
  border-radius: 6px;
}

/* 单个图片项样式 */
.image-item {
  width: 100%;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  margin-bottom: 6px;
  display: flex;
  flex-direction: column;
  overflow: visible;
  background: #ffffff;
  box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
}

/* 图片项悬停效果 */
.image-item:hover {
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.15);
  transform: translateY(-1px);
}

/* 预览图片容器样式 */
.preview-container {
  position: relative;
  display: flex;
  justify-content: center;
  padding: 0px;
  background: #ffffff;
  border-radius: 8px 8px 0 0;
}

/* 删除按钮样式 */
.delete-btn {
  position: absolute !important;
  top: 6px;
  right: 6px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9) !important;
  border: 1px solid #ebeef5 !important;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
  color: #909399;
  transition: all 0.3s ease;
  z-index: 10;
}

.delete-btn:hover {
  background: #ff5757 !important;
  color: white !important;
  transform: scale(1.1);
}

/* 预览图片样式 */
.preview-image {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: none;
  object-fit: scale-down;
  align-self: center;
  border-radius: 4px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
  border: 1px solid #f0f0f0;
}

/* 元数据表单容器样式 */
.metadata-form {
  padding: 15px;
  background: #ffffff;
  border-top: 1px solid #ebeef5;
}

/* 表单行样式 */
.form-row {
  display: flex;
  gap: 12px;
  margin-bottom: 12px;
  align-items: flex-end;
}

/* 表单项基础样式 */
.form-item {
  flex: 1;
}

/* 全宽表单项 */
.form-item.full-width {
  flex: 0 0 100%;
}

/* 下拉选择框和输入框共用样式 */
.form-select,
.form-input {
  width: 100%;
  padding: 0px 0px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  margin-top: 5px;
  font-size: 14px;
  transition: border-color 0.2s;
  box-sizing: border-box;
}

.form-select:focus,
.form-input:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
.anser-text{
    width: 100%;
  /* 宽度占满容器 */
  padding: 0px;
  /* 内边距0px */
  border: 1px solid #dcdfe6;
  /* 1px浅灰色边框 */
  border-radius: 4px;
  /* 4px圆角 */
  margin-top: 0px;
  /* 顶部外边距4px */
}
/* 下拉选择框特有样式 */
.form-select {
  background: white;
  cursor: pointer;
}

/* 禁用输入框样式 */
.form-input:disabled {
  background: #f5f7fa;
  cursor: not-allowed;
}

/* 标签样式 */
label {
  font-size: 13px;
  color: #606266;
  font-weight: 500;
}

/* 标签容器样式 */
.tags-drop-container {
  min-height: 28px;
  border: 1px dashed #dcdfe6;
  border-radius: 4px;
  padding: 6px 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: center; /* 添加这行实现垂直居中 */
  gap: 6px;
  margin-top: 5px;
  background: #fafafa;
  transition: all 0.3s ease;
}

.tags-drop-container:hover {
  border-color: #409eff;
  background: #f0f8ff;
}

/* 拖拽时的样式 */
.tags-drop-container.dragover {
  border-color: #409eff;
  background: #ecf5ff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

/* 标签项样式 */
.tag-item {
  margin: 1px;
  background: #ecf5ff;
  border-color: #d9ecff;
  color: #409eff;
  border-radius: 3px;
  padding: 3px 6px;
  font-size: 12px;
}

.tag-item:hover {
  background: #409eff;
  color: white;
}

/* 拖拽提示样式 */
.drop-hint {
  color: #909399;
  font-size: 12px;
  padding: 6px;
  text-align: center;
  width: 100%;
  font-style: italic;
}

/* 批量设置对话框样式 */
:deep(.el-dialog) {
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

:deep(.el-dialog__header) {
  background: #f5f7fa;
  padding: 15px 20px;
  border-bottom: 1px solid #ebeef5;
}

:deep(.el-dialog__title) {
  font-size: 1.1rem;
  font-weight: 600;
  color: #303133;
}

:deep(.el-dialog__body) {
  padding: 20px;
}

:deep(.el-dialog__footer) {
  padding: 12px 20px;
  background: #f5f7fa;
  border-top: 1px solid #ebeef5;
}

/* Element UI 组件样式优化 */
:deep(.el-button) {
  border-radius: 4px;
  transition: all 0.3s ease;
  font-size: 13px;
}

:deep(.el-button--primary) {
  background: #409eff;
  border-color: #409eff;
  box-shadow: 0 1px 3px rgba(64, 158, 255, 0.2);
}

:deep(.el-button--primary:hover) {
  background: #66b1ff;
  border-color: #66b1ff;
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(64, 158, 255, 0.3);
}

:deep(.el-select) {
  width: 100%;
}

:deep(.el-cascader) {
  width: 100%;
}

:deep(.el-tag) {
  border-radius: 3px;
  padding: 3px 6px;
  display: flex;
  align-items: center;
  font-size: 12px;
}

:deep(.el-tag .el-tag__close) {
  border-radius: 50%;
  background: transparent;
  color: #909399;
}

:deep(.el-tag .el-tag__close:hover) {
  background: rgba(0, 0, 0, 0.1);
  color: #303133;
}

/* 滚动条样式优化 */
.image-container::-webkit-scrollbar {
  width: 6px;
}

.image-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.image-container::-webkit-scrollbar-thumb {
  background: #c0c4cc;
  border-radius: 3px;
}

.image-container::-webkit-scrollbar-thumb:hover {
  background: #909399;
}

@media (max-width: 768px) {
  .toolbar {
    flex-wrap: wrap;
    padding: 10px;
  }
  
  .form-row {
    flex-direction: column;
    gap: 8px;
  }
  
  .form-item {
    width: 100%;
  }
  
  .metadata-form {
    padding: 12px;
  }
  
  .image-container {
    padding: 10px;
    gap: 12px;
  }
}

/* 答案输入容器样式 */
.answer-input-container {
  display: flex;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  margin-top: 4px;
  height: 32px;
  overflow: hidden;
}

/* 表单输入框高度统一 */
.form-input {
  height: 100%;
}

.answer-section {
  flex: 1;
  padding: 0px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 1px solid #eee;
  height: 100%;
}

.answer-section:last-child {
  border-right: none;
}

.answer-btn {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 0;
  font-size: 12px;
}

.text-answer {
  flex: 10;
}

.form-input {
  height: 32px;
}
</style>